/******************************************************************************
* Copyright 2022 The Airos Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include <cstring>
#include <glog/logging.h>
#include "codec/fake_obu_rsu_codec/fake_obu_rsu_codec.h"

namespace air {
namespace codec {

std::string FakeObuRsuCodec::Encode(uint8_t msg_type, const std::string& data) {
  if (data.empty()) {
    return "";
  }
  const char* data_buf = data.data();
  int spdu_len = data.size();

  std::string pack;
  pack.assign(spdu_len + 8 + 3, '\0');
  pack[0] = 0xfa;  ///< 包头
  pack[1] = 0xfb;  ///< 包头
  pack[2] = 0x01;  ///< 版本号
  pack[3] = 0x01;  ///< 版本号
  pack[4] = 0x22;
  pack[5] = msg_type;
  pack[6] = spdu_len / 256;
  pack[7] = spdu_len % 256;
  memcpy(&pack[8], data_buf, spdu_len);  /// ASN数据流体
  pack[8 + spdu_len] = 0;  ///< 校验码
  for (int i = 2; i < 8 + spdu_len; i++) {
    pack[8 + spdu_len] ^= pack[i];
  }
  pack[9 + spdu_len] = 0xec;  ///< 包尾
  pack[10 + spdu_len] = 0xed;  ///< 包尾

  return pack;
}

int FakeObuRsuCodec::Decode(
    const std::string& pack,
    uint8_t* msg_type,
    std::string* data) {
  if (pack.size() < 11
      || pack.size() > 1900
      || data == nullptr || msg_type == nullptr) {
    LOG(ERROR) << "intput param error";
    return -1;
  }
  /// 检查包头包尾是指定字符
  if (uint8_t(pack[0]) != 0xfa || uint8_t(pack[1]) != 0xfb) {
    LOG(ERROR) << "frame header error";
    return -1;
  }
  if (uint8_t(pack[pack.size() - 1]) != 0xed
      || uint8_t(pack[pack.size() - 2]) != 0xec) {
    LOG(ERROR) << "frame tail error";
    return -1;
  }
  /// 检查实际长度与标识长度一致
  uint16_t len = uint8_t(pack[6]) << 8 | uint8_t(pack[7]);
  if (pack.size() - 11 != len) {
    LOG(ERROR) << "frame length error";
    return -1;
  }
  /// 检查校验码一致
  uint8_t check_code = 0x00;
  for (int i = 2; i < 8 + len; i++) {
    check_code ^= uint8_t(pack[i]);
  }
  if (uint8_t(pack[8 + len]) != check_code) {
    LOG(ERROR) << "frame check_code error";
    return -1;
  }
  /// 返回数据
  *msg_type = uint8_t(pack[5]);
  data->clear();
  data->append(&pack[8], len);
  return 0;
}

}  // namespace codec
}  // namespace air
